package com.apes.autoparts.supplier.todo;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.supplier.contrast.ContrastService;
import com.apes.autoparts.supplier.platform.SupplierPlatformItemRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.cache.Cache;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.StringUtil;
import com.apes.framework.util.Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/***
 * 1. 用于判断当前数据是否为 增 删 改
 * 2. 判断是否已存在待办
 *
 */

@Service("todoCheckService")
public class SupplierPlatformTodoCheckService extends DomainService {

    @Autowired
    private BusinessAttributeValueRepository businessAttributeValueRepository;
    @Autowired
    private SupplierPlatformTodoRepository todoRepository;
    @Autowired
    private ContrastService contrastService;
    @Autowired
    private SupplierPlatformItemRepository supplierPlatformItemRepository;
    @Autowired
    private Cache cache;

    private static final String CATEGORY_CACHE_NAME = "categoryCache";
    private static final String CONTRAST_BRAND_CACHE_NAME = "contrastBrandCache";

    //    private List<String> categories;
    // 重点更新字段
    private final List<String> importantFields = Arrays.asList("brandName", "originPlace", "partCode");


    /***
     * 入口
     */
    public SupplierPlatformTodo todoCheck(SimpleRequest request) {

        JSONObject param = request.getJO();

        // 获取待办属性
        BusinessAttributeValue property = getProperty(param);

        // 判断是否已存在
//        SupplierPlatformTodo oldTodo = checkExists(param, property);
//        if (oldTodo != null) return oldTodo;

        // 判断是否新增 修改 删除
        SupplierPlatformTodo todo = convertToTodo(param, property);
        if( property.getId().equalsIgnoreCase("Todo.property.update") ) {
            // 判断是否为重要属性修改
            if ( checkImportantUpdate(param) ) {
                todo.setBatch(param.getString("batch")); // 设置批次
                return todoRepository.saveAndFlush(todo);
            } else {
                request.setData(prepareModel(todo));
                contrastService.updateUnImportant(request);
               return null;
            }
        } else if( property.getId().equalsIgnoreCase("Todo.property.create") ) {
            todo.setBatch(param.getString("batch")); // 设置批次
            return todoRepository.saveAndFlush(todo);
        } else {
            return delete(todo, property);
        }

    }


    /***
     * 判断待办属性（增 删 改）
     */
    private BusinessAttributeValue getProperty(JSONObject param) {
        String property = null;

        if (param.getBooleanValue("deleteFlag")) {
            property = "Todo.property.delete";
        } else if (param.getBooleanValue("createFlag")) {
            property = "Todo.property.create";
        } else {
            property = "Todo.property.update";
        }
        return businessAttributeValueRepository.findOne(property);
    }

    /***
     * 判断是否重要属性被修改
     */
    private boolean checkImportantUpdate(JSONObject param) {
        return importantFields.stream().anyMatch(field -> {
            return !checkEqual(param.getString(field), param.getString("old" + StringUtil.toUpperFirst(field)));
        });
    }

    /***
     * 用于比较两个字符串是否相等
     */
    private boolean checkEqual(String str, String str1) {
//        if (str == null && str1 == null) return true;
        if (StringUtils.isEmpty(str) && StringUtils.isEmpty(str1)) return true;
        if (str == null || str1 == null) return false;
        return str.equals(str1);
    }


    /***
     * 判断是否已存在待办
     */
    private SupplierPlatformTodo checkExists(JSONObject param, BusinessAttributeValue property) {
        SupplierPlatformTodo todo = todoRepository.findOne(JpaDsl.toCriteriaByEq(
                "supplierPlatformItem.id", param.getJSONObject("supplierPlatformItem").getString("id"),
                "source", param.getString("source")
        )).orElse(null);

        if (todo == null) return null;
        return getPriority(todo, property, param);
    }

    /***
     * 存在相同的数据，将最新的数据直接更新到已创建待办中去
     */
    private SupplierPlatformTodo updateTodo(SupplierPlatformTodo todo, JSONObject param) {
        todo.setBrandName(param.getString("brandName"));
        todo.setOriginPlace(param.getString("originPlace"));
        todo.setPartCode(param.getString("partCode"));
        todo.setPartCodeName(param.getString("partCodeName"));
        todo.setUnit(param.getString("unit"));

        todo.setStockQty(param.getDoubleValue("stockQty"));
        todo.setUntaxPrice(param.getDoubleValue("untaxPrice"));
        return todoRepository.saveAndFlush(todo);
    }


    /***
     * 验证新老的权重
     * 状态权重（允许更新其他状态）delete > create > update
     * 1. 删除
     * 2. 新增 -> 修改 = 新增
     * 3. 修改 -> 修改 = 修改
     */
    private SupplierPlatformTodo getPriority(SupplierPlatformTodo todo, BusinessAttributeValue property, JSONObject param) {

        String oldProperty = todo.getProperty().getId();
        String newProperty = property.getId();

        if (newProperty.equals("Todo.property.delete")) {
            // 直接删除
            return delete(todo, property);
        } else {
            return createOrUpdate(todo, param);
        }
    }


    /***
     * 处理待办： 删除
     */
    private SupplierPlatformTodo delete(SupplierPlatformTodo todo, BusinessAttributeValue property) {
        todo.setProperty(property);
        todo.setRemark("远程数据已删除，系统自动处理");
        todo.setResolves( MapUtil.mapper(
                "id", "yyadmin"
        ));
        todo.setResolveDate(new Date());
        todo.setState("confirm");
        todo.setSupplierPlatformItem(supplierPlatformItemRepository.findOne(todo.getSupplierPlatformItem().getId()));
        // 直接处理数据
        SimpleRequest request = new SimpleRequest();
        request.setData(prepareModel(todo));
        contrastService.delete(request);
        todo = todoRepository.saveAndFlush(todo);
        return todo;
    }

    /***
     * 处理待办：新增
     */
    private SupplierPlatformTodo createOrUpdate(SupplierPlatformTodo todo, JSONObject param) {
        return updateTodo(todo, param);
    }


    /***
     * 构建数据
     */
    public JSONObject prepareModel(SupplierPlatformTodo todo) {
        SupplierPlatformTodoParse todoParse = todo.getTodoParse();
        JSONObject param = new JSONObject();
        param.put("SUPPLIER_PLATFORM_ITEM_ID", todo.getSupplierPlatformItem().getId());
        param.put("SUPPLIER_PLATFORM_SOURCE", todo.getSource());
        param.put("BUSINESS_ID", todo.getOldPartCode() != null ? todo.getOldPartCode() : todo.getPartCode());
        param.put("SUPPLIER_ID", "00" + todo.getSupplierPlatformItem().getSupplierMap().get("id").toString());
        param.put("SUPPLIER_NAME", todo.getSupplierPlatformItem().getSupplierMap().get("name").toString());
        param.put("UNTAX_PRICE", todo.getUntaxPrice());
        param.put("INVENTORY_QUANTITY", todo.getStockQty());
        param.put("ORIGIN", todo.getOriginPlace());
        param.put("PART_NAME", todo.getPartCodeName());
        param.put("UOM_NAME", todo.getUnit());
        param.put("CONTRAST_BRAND_ID", todoParse != null && todoParse.getContrastBrands() != null ? todoParse.getContrastBrands().get("id") : null);
        param.put("CONTRAST_BRAND_NAME", todoParse != null && todoParse.getContrastBrands() != null ? todoParse.getContrastBrands().get("name") : null);
        param.put("CONTRAST_ORIGIN", todoParse != null ? todoParse.getContrastOriginPlace() : null);
        param.put("CONTRAST_PART_ID", todoParse != null ? todoParse.getContrastPartCode() : null);
        param.put("CATEGORY_ID", todoParse != null && todoParse.getContrastCategories() != null ? todoParse.getContrastCategories().get("id") : null);


        return param;
    }

    /***
     * 将传入的数据转化为 Todo模型
     */
    private SupplierPlatformTodo convertToTodo(JSONObject param, BusinessAttributeValue property) {
        // 原始数据
        SupplierPlatformTodo todo = new SupplierPlatformTodo();
        todo.setSupplierPlatformItem(
                supplierPlatformItemRepository.findOne(param.getJSONObject("supplierPlatformItem").getString("id"))
        );
        todo.setSource(param.getString("source"));
        todo.setOldBrandName(param.getString("oldBrandName"));
        todo.setBrandName(param.getString("brandName"));
        todo.setOldOriginPlace(param.getString("oldOriginPlace"));
        todo.setOriginPlace(param.getString("originPlace"));
        todo.setOldPartCode(param.getString("oldPartCode"));
        todo.setPartCode(param.getString("partCode"));
        todo.setOldPartCodeName(param.getString("oldPartCodeName"));
        todo.setPartCodeName(param.getString("partCodeName"));
        todo.setOldUnit(param.getString("oldUnit"));
        todo.setUnit(param.getString("unit"));
        todo.setStockQty(param.getDoubleValue("stockQty"));
        todo.setUntaxPrice(param.getDoubleValue("untaxPrice"));
        todo.setState("waitingResolve");
        todo.setProperty(property);

        // 编译记录
        JSONObject historyParse = getHistoryParse(todo, param);
        if (historyParse.size() == 0) return todo;
        else todo.setProperty(businessAttributeValueRepository.findOne("Todo.property.update"));
        SupplierPlatformTodoParse todoParse = new SupplierPlatformTodoParse();
        todoParse.setTodo(todo);
        todoParse.setContrastBrands(historyParse.getString("CONTRAST_BRAND_ID") != null ?  MapUtil.mapper(
            "id", historyParse.getString("CONTRAST_BRAND_ID")
        ): null);
        todoParse.setContrastCategories(historyParse.getString("CATEGORY_ID") != null ?  MapUtil.mapper(
                "id", historyParse.getString("CATEGORY_ID")
        ) : null);
        todoParse.setContrastOriginPlace(historyParse.getString("CONTRAST_ORIGIN"));
        todoParse.setContrastPartCode(historyParse.getString("CONTRAST_PART_ID"));

        todo.setTodoParse(todoParse);
        return todo;
    }

    /***
     * 获取历史编译记录
     */
    private JSONObject getHistoryParse(SupplierPlatformTodo todo, JSONObject param) {
        return contrastService.findOne(todo.getSupplierPlatformItem(), param.getString("oldPartCode"), param.getString("source"));
    }

    /***
     * 获取多个待办历史编译记录
     */
    private Map getHistoryParses(String supplierPlatformItemId, JSONArray param) {
        JSONObject json = new JSONObject();
        List<String> sources = param.stream().map(o -> {
            JSONObject item = (JSONObject) o;
            return item.getString("source");
        }).collect(Collectors.toList());
        json.put("SUPPLIER_PLATFORM_ITEM_ID", supplierPlatformItemId);
        json.put("SUPPLIER_PLATFORM_SOURCES", sources);
        JSONArray array = contrastService.queryInsertBusinessInfos(json);
        Map map = new HashMap();
        // 转化成map对象,方便获取
        array.forEach(o -> {
            JSONObject item = (JSONObject) o;
            SupplierPlatformTodoParse todoParse = new SupplierPlatformTodoParse();
            map.put(item.getString("SUPPLIER_PLATFORM_SOURCE"), item);
        });
        return map;
    }
    /***
     * 批量推送待办
     * 1.获取数据属性
     * 2.将数据转化成待办数据
     *
     */
    public void todoChecks(SimpleRequest request) {
        JSONArray param = request.getJO().getJSONArray("data");
        List<SupplierPlatformTodo> todos = JSONArray.parseArray(param.toString(), SupplierPlatformTodo.class);;
        String attributes = request.getJO().getString("property");
        BusinessAttributeValue property;
        // 创建待办
        if ( "create".equals(attributes) ) {
            property = businessAttributeValueRepository.findOne("Todo.property.create");
            for (SupplierPlatformTodo todo : todos) {
                todo.setProperty(property);
                todo.setState("waitingResolve");
            }
            todoRepository.save(todos);
            // 更新价格和库存数据
        } else if ( "update".equals(attributes) ) {
            updateBusinessInfos(param);
            // 重要属性发生改变，产生待办
        } else if ( "importUpdate".equals(attributes) ) {
            Map historyParses = getHistoryParses(request.getJO().getString("supplierPlatformItemId"), param);
            property = businessAttributeValueRepository.findOne("Todo.property.update");
            for (SupplierPlatformTodo todo : todos) {
                // 获取当前待办历史编译记录
                JSONObject historyParse = (JSONObject) historyParses.get(todo.getSource());
                if (historyParse != null) {
                    todo.setTodoParse(getTodoParse(historyParse, todo));
                }
                todo.setProperty(property);
                todo.setState("waitingResolve");
            }
            todoRepository.save(todos);
        } else if ( "delete".equals(attributes) ) {
            property = businessAttributeValueRepository.findOne("Todo.property.delete");
            for (SupplierPlatformTodo todo : todos) {
                delete(todo, property);
            }
        }

    }

    private void updateBusinessInfos(JSONArray param) {
        for (Object o : param) {
            JSONObject json = (JSONObject) o;
            json.put("supplierPlatformItemId", json.getJSONObject("supplierPlatformItem").getString("id"));
            contrastService.updateSupplierData(json);
        }
    }


    private SupplierPlatformTodoParse getTodoParse(JSONObject params, SupplierPlatformTodo todo) {
        SupplierPlatformTodoParse todoParse = new SupplierPlatformTodoParse();
        todoParse.setTodo(todo);
        todoParse.setContrastBrands(params.getString("CONTRAST_BRAND_ID") != null ? MapUtil.mapper(
                "id", params.getString("CONTRAST_BRAND_ID"),"name", params.getString("CONTRAST_BRAND_NAME")
        ): new HashMap());
        todoParse.setContrastCategories(params.getString("CATEGORY_ID") != null ?  MapUtil.mapper(
                "id", params.getString("CATEGORY_ID")
        ) : new HashMap());
        todoParse.setContrastOriginPlace(params.getString("CONTRAST_ORIGIN"));
        todoParse.setContrastPartCode(params.getString("CONTRAST_PART_ID"));
        todo.setTodoParse(todoParse);

        todoParse.setContrastPartCode("");
        return todoParse;
    }

}
